#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <malloc.h>
#include <unistd.h>

#include "upgrade.h"

UPGRADE_PARAM upgrade_param;

char new_firmware_name[512] = {0};
char new_firmware_version[256] = {0};
uint32 new_firmware_version_num = 0;

int parseProtocal(unsigned char *data, int len);
int boot_close_dev();


int get_file_size(char *filename)
{
	if((NULL == filename)||(0 == strlen(filename)))
	{
		WD_ERR("the param is error!\n");
		return 0;
	}

	struct stat statbuf;
	memset((uint8 *)&statbuf, 0x00, sizeof(struct stat));
	stat(filename, &statbuf);
	int size = statbuf.st_size;

	return size;
}

int check_file_exit(void)
{
	int file_size = 0;

	file_size = get_file_size(UPGRADE_FILE);
	if((0 == file_size) || (2*1024*1024 < file_size))//此处最大文件大小待确认
	{
		WD_ERR("%s file_size = %d, error!\n", UPGRADE_FILE, file_size);
		boot_close_dev();
		return -1;//文件不存在或文件错误
	}

	return 0;//文件存在
}


/*
    根据PID与VID检查指定设备是否挂载。
*/
int get_device_descriptor(struct libusb_device_descriptor *dev_desc, usb_dev* user_device)
{
    int rv = -2;
    int i = 0;
    int ret = -2;

    libusb_device **devs;
    libusb_device *dev;

    pthread_mutex_lock(&(dev_ofprint->mutex));  // 加锁
    rv = libusb_get_device_list(NULL, &devs);
    if (rv < 0) {
        pthread_mutex_unlock(&(dev_ofprint->mutex));  // 解锁

        return rv;
    }

    //遍历USB设备

    i = 0;
    while ((dev = devs[i++]) != NULL) {
        rv = libusb_get_device_descriptor(dev, dev_desc);
        if(rv < 0) {
            ret = -1;
            break;
        }

        if(dev_desc->idProduct == user_device->pid && dev_desc->idVendor == user_device->vid)
        {
            user_device->dev = dev;
            user_device->devs = devs;
            user_device->bInterfaceNumber = 0;
            D_DBG("bInterfaceNumber = %d\n", user_device->bInterfaceNumber);
            ret = 0;
            break;
        }
    }
    libusb_free_device_list(devs, 1);

    pthread_mutex_unlock(&(dev_ofprint->mutex));  // 解锁

    return ret;
}

int get_device_endpoint(struct libusb_device_descriptor *dev_desc, usb_dev* user_device)
{
    int rv = -2;
    int i,j,k;
    struct libusb_config_descriptor *conf_desc;
    //unsigned char isFind = 0;

    for (i = 0; i < dev_desc->bNumConfigurations; i++)
    {
        if(user_device->dev != NULL)
            rv = libusb_get_config_descriptor(user_device->dev, i, &conf_desc);

        if(rv < 0) {
            return -1;
        }

        for (j = 0; j < conf_desc->bNumInterfaces; j++)
        {
            for (k=0; k < conf_desc->interface[j].num_altsetting; k++)
            {
                if(conf_desc->interface[j].altsetting[k].bInterfaceClass == user_device->bInterfaceClass)
                {
                    //if(match_with_endpoint(&(conf_desc->interface[j].altsetting[k] ), user_device))
                    {
                        user_device->bInterfaceNumber = conf_desc->interface[j].altsetting[k].bInterfaceNumber;
                        libusb_free_config_descriptor(conf_desc);
                        rv = 0;
                        return rv;
                    }
                }
            }
        }
    }

    return -2;  //don't find user device
}

int boot_open_dev(void)
{
	UPGRADE_PARAM *this = &upgrade_param;
    libusb_device_handle *handle = NULL;
    struct libusb_device_descriptor udev_desc;
    int ret = 0;

    this->udev.vid = BOOT_USB_VID;
    this->udev.pid = BOOT_USB_PID;
    DBG("boot_open_dev ===========================>enter \n");
    //3. search for specified usb device.
    ret = get_device_descriptor(&udev_desc, &(this->udev));
    if(0 > ret)
    {
        WD_DBG("get_device_descriptor failed.\n");
        return -1;
    }
    pthread_mutex_lock(&(dev_ofprint->mutex));  // 加锁

    handle = libusb_open_device_with_vid_pid(NULL, BOOT_USB_VID, BOOT_USB_PID);
    if(NULL == handle)
    {
        WD_ERR("vid=0x%4x, pid=0x%04x usb device open failed!!!\n", BOOT_USB_VID, BOOT_USB_PID);
        pthread_mutex_unlock(&(dev_ofprint->mutex));  // 加锁
        return -1;
    }
#if 1

    //get_device_descriptor(&(this->udev_desc), &(this->udev));
    ret = libusb_claim_interface(handle, this->udev.bInterfaceNumber);
    if(0 > ret)
    {
        DBG("libusb_claim_interface   first error \n");
        ret = libusb_detach_kernel_driver(handle, this->udev.bInterfaceNumber);
        if(0 > ret)
        {
            WD_ERR("libusb_detach_kernel_driver failed.\n");
             pthread_mutex_unlock(&(dev_ofprint->mutex));  // 加锁
            return -1;
        }

        ret = libusb_claim_interface(handle, this->udev.bInterfaceNumber);
        if(ret < 0)
        {
            WD_ERR("libusb_claim_interface failed.\n");
            pthread_mutex_unlock(&(dev_ofprint->mutex));  // 加锁
            return -1;
        }
    }
#endif
    pthread_mutex_unlock(&(dev_ofprint->mutex));  // 加锁

    this->usb_handle = handle;

    D_DBG("vid=0x%4x, pid=0x%04x usb device open success.\n", BOOT_USB_VID, BOOT_USB_PID);

    DBG("boot_open_dev <=========================== exit \n");
    return 0;
}

int boot_close_dev(void)
{
	UPGRADE_PARAM *this = &upgrade_param;


    if(NULL == this->usb_handle)
    {
        WD_ERR("vid=0x%4x, pid=0x%04x usb device not open!!!\r\n", BOOT_USB_VID, BOOT_USB_PID);
        return -1;
    }

   libusb_close(this->usb_handle);


    this->usb_handle = NULL;

    return 0;
}

int boot_write_usb(unsigned char *data, int len)
{
	UPGRADE_PARAM *this = &upgrade_param;
  int ret = 0;

    int write_len = -1;
    libusb_device_handle *handle = this->usb_handle;

    if((NULL == data)||(0 == len))
    {
        WD_ERR("the param is error!!!\n");
        return -1;
    }

    if(NULL == handle)
    {
        WD_ERR("%s not open, error!!!\n", BOOT_DEV_NAME);
        return -1;
    }

#if 0
    D_DBG("write %d bytes to %s:\n", len, BOOT_DEV_NAME);
    int i;
    int n;
    (len > 64)?(n = 64):(n = len);
    for (i = 0; i < n; i++)
    {
        DBG("%02x ", data[i]);
        if(0 == (i + 1) % 32)
            DBG("\n");
    }
    DBG("\n");
#endif
    //D_DBG("endpoint = %d\n", INT_SEND_EP);
    //if(0 > libusb_interrupt_transfer(handle, 0x04, data, len, &(write_len), 0))
    pthread_mutex_lock(&(dev_ofprint->bulk_mutex));
    ret = libusb_bulk_transfer(handle, INT_SEND_EP, data, len, &(write_len), 0);
    pthread_mutex_unlock(&(dev_ofprint->bulk_mutex));
    if(0 > ret)
    {
        //WD_ERR("libusb_interrupt_transfer write failed!!!\r\n");
        WD_ERR("libusb_bulk_transfer write failed ret = %d!!!\r\n", ret);
        return -1;
    }
    usleep(WR_DELAY_MS * 1000);

    return write_len;
}



int app_boot_write_usb(unsigned char *data, int len)
{
	UPGRADE_PARAM *this = &upgrade_param;
  int ret = 0;

    int write_len = -1;
    libusb_device_handle *handle = this->usb_handle;

    if((NULL == data)||(0 == len))
    {
        WD_ERR("the param is error!!!\n");
        return -1;
    }

    if(NULL == handle)
    {
        WD_ERR("%s not open, error!!!\n", BOOT_DEV_NAME);
        return -1;
    }

#if 0
    D_DBG("write %d bytes to %s:\n", len, BOOT_DEV_NAME);
    int i;
    int n;
    (len > 64)?(n = 64):(n = len);
    for (i = 0; i < n; i++)
    {
        DBG("%02x ", data[i]);
        if(0 == (i + 1) % 32)
            DBG("\n");
    }
    DBG("\n");
#endif
    //D_DBG("endpoint = %d\n", INT_SEND_EP);
    //if(0 > libusb_interrupt_transfer(handle, 0x04, data, len, &(write_len), 0))
    pthread_mutex_lock(&(dev_ofprint->bulk_mutex));
    ret = libusb_bulk_transfer(handle, INT_SEND_EP, data, len, &(write_len), 0);

    pthread_mutex_unlock(&(dev_ofprint->bulk_mutex));
    if(0 > ret)
    {
        //WD_ERR("libusb_interrupt_transfer write failed!!!\r\n");
        WD_ERR("libusb_bulk_transfer write failed ret = %d!!!\r\n", ret);
        //ret = libusb_bulk_transfer(handle, INT_SEND_EP, data, len, &(write_len), 0);
        return -1;
    }



    usleep(WR_DELAY_MS * 1000);

    return write_len;
}


int boot_read_usb(unsigned char *data, int len)
{
	UPGRADE_PARAM *this = &upgrade_param;
  int ret = 0;

    int read_len = -1;
    libusb_device_handle *handle = this->usb_handle;

    if((NULL == data)||(0 == len))
    {
        WD_ERR("the param is error!!!\n");
        return -1;
    }

    if(NULL == handle)
    {
        WD_ERR("%s not open, error!!!\n", BOOT_DEV_NAME);
        return -1;
    }

    //D_DBG("start read.\n");
    //if(0 != libusb_interrupt_transfer(handle, 0x84, data, len, &read_len, 0))
    pthread_mutex_lock(&(dev_ofprint->bulk_mutex));
    ret = libusb_bulk_transfer(handle, INT_RECV_EP, data, len, &read_len, TRANSFER_TIMEOUT);
    pthread_mutex_unlock(&(dev_ofprint->bulk_mutex));


    if(0 != ret)
    {
        //WD_ERR("libusb_interrupt_transfer read failed!!!\n");
        WD_ERR("libusb_bulk_transfer read failed ret = %d!!!\n", ret);
        return -1;
    }
#if 0
    D_DBG("read %d bytes from %s:\n", read_len, BOOT_DEV_NAME);
    int i;
    int n;
    (read_len > 64)?(n = 64):(n = read_len);
    for (i = 0; i < n; i++)
    {
        DBG("%02x ", data[i]);
        if(0 == (i + 1) % 32)
            DBG("\r\n");
    }
    DBG("\n");
#endif
    //D_DBG("end read.\n");
    usleep(WR_DELAY_MS * 1000);
    return read_len;
}
/****************************Info**********************************************
* Name:    InvertUint8
* Note:     把字节颠倒过来，如0x12变成0x48 0x12: 0001 0010 0x48: 0100 1000
*****************************************************************************/
void InvertUint8(unsigned char *dBuf,unsigned char *srcBuf)
{
    int i;
    unsigned char tmp[4]={0};
    for(i=0;i< 8;i++)
    {
        if(srcBuf[0]& (1 << i))
            tmp[0]|=1<<(7-i);
    }
    dBuf[0] = tmp[0];
}

void InvertUint16(unsigned short *dBuf,unsigned short *srcBuf)
{
    int i;
    unsigned short tmp[4]={0};
    for(i=0;i< 16;i++)
    {
        if(srcBuf[0]& (1 << i))
            tmp[0]|=1<<(15 - i);
    }
    dBuf[0] = tmp[0];
}

/****************************Info**********************************************
 * Name:    CRC-16/X25          x16+x12+x5+1
 * Width:	16
 * Poly:    0x1021
 * Init:    0xFFFF
 * Refin:   True
 * Refout:  True
 * Xorout:  0XFFFF
 * Note:
 *****************************************************************************/
#if 1
unsigned short CRC16_X25(char *data, unsigned int datalen)
{
    unsigned short wCRCin = 0xFFFF;
    unsigned short wCPoly = 0x1021;
    unsigned char wChar = 0;
    while (datalen--)
    {
        wChar = *(data++);
        InvertUint8(&wChar,&wChar);
        wCRCin ^= (wChar << 8);
        for(int i = 0;i < 8;i++)
        {
            if(wCRCin & 0x8000)
                wCRCin = (wCRCin << 1) ^ wCPoly;
            else
                wCRCin = wCRCin << 1;
        }
    }
    InvertUint16(&wCRCin,&wCRCin);
    return (wCRCin^0xFFFF);
}
#else
unsigned short CRC16_X25(char *data, unsigned int datalen)
{
    unsigned short wCRCin = 0xFFFF;
    unsigned short wCPoly = 0x1021;
    InvertUint16(&wCPoly,&wCPoly);
    while (datalen--)
    {
        wCRCin ^= *(data++);
        for(int i = 0;i < 8;i++)
        {
            if(wCRCin & 0x01)
                wCRCin = (wCRCin >> 1) ^ wCPoly;
            else
                wCRCin = wCRCin >> 1;
        }
    }
    return (wCRCin^0xFFFF);
}
#endif


uint8 Check_BCC(uint8 *data, int len)
{
    uint8 bcc = 0;

    if((NULL == data)||(0 == len))
    {
        WD_ERR("the param is error!!!\n");
        return 0xff;
    }

    for(int i = 0; i < len; i++)
    {
        bcc ^= data[i];
    }

    return bcc;
}

int readEFlash(unsigned int addr, unsigned char len)
{
    uint8 buf[100] = {0xAA, 0xD0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55};
    int cmd_len = 11;

    buf[4] = addr & 0xff;
    buf[5] = (addr>>8) & 0xff;
    buf[6] = (addr>>16) & 0xff;
    buf[7] = (addr>>24) & 0xff;
    buf[8] = len;
    buf[9] = Check_BCC(buf, cmd_len);

    boot_write_usb(buf, cmd_len);

    uint8 buf_read[500] = {0};
    if(0 < boot_read_usb(buf_read, len + 10))
    {
        D_DBG("read eflash data.\n");
    }
    return 0;
}

int eraseEFlash(void)
{
    uint8 buf[500] = {0xAA, 0xD3, 0x00, 0x00, 0x00, 0x55};
    int cmd_len = 4+2;

    buf[4] = Check_BCC(buf, cmd_len);

    boot_write_usb(buf, cmd_len);

    UP_PROT_PACKET *p = &(upgrade_param.prot_packet_usb);
    int ret = -1;
    uint8 buf_read[500] = {0};
    int read_len = 0;
    read_len = boot_read_usb(buf_read, 64);
    if(0 < read_len)
    {
        //D_DBG("read %d byte.\n", read_len);
        p->prot_state = UP_PACKET_IDLE;
        if((0 == parseProtocal(buf_read, read_len))\
            &&(UP_PACKET_RECV_SUCCESS == p->prot_state))
        {
            //memcpy(this->dev_sn, p->prot_data, p->prot_data_cnt);
            if((1 == p->prot_data_cnt)&&(0 == p->prot_data[0]))
                ret = 0;
        }
        p->prot_state = UP_PACKET_IDLE;
    }
    else
    {
        WD_ERR("read response failed!!!\n");
    }

    return ret;
}

int downloadCodeToEFlash(unsigned int addr, char *data, int len)
{
    uint8 buf[500] = {0xAA, 0xD7};
    int cmd_len = 4 + 4 + len + 2;

    buf[2] = (4+len)&0xff;
    buf[3] = ((4+len)>>8)&0xff;
    buf[4] = addr & 0xff;
    buf[5] = (addr>>8) & 0xff;
    buf[6] = (addr>>16) & 0xff;
    buf[7] = (addr>>24) & 0xff;
    memcpy(&buf[8], data, len);

    //D_DBG("cmd_len = %d, bcc = 0x%02x", cmd_len, Check_BCC(buf, cmd_len));
    buf[4+4+len+1] = 0x55;
    buf[4+4+len] = Check_BCC(buf, cmd_len);

    boot_write_usb(buf, 250);

    UP_PROT_PACKET *p = &(upgrade_param.prot_packet_usb);
    int ret = -1;
    uint8 buf_read[500] = {0};
    int read_len = 0;
    read_len = boot_read_usb(buf_read, 64);
    if(0 < read_len)
    {
        //D_DBG("read %d byte.\n", read_len);
        p->prot_state = UP_PACKET_IDLE;
        if((0 == parseProtocal(buf_read, read_len))\
            &&(UP_PACKET_RECV_SUCCESS == p->prot_state))
        {
            //memcpy(this->dev_sn, p->prot_data, p->prot_data_cnt);
            if((1 == p->prot_data_cnt)&&(0 == p->prot_data[0]))
                ret = 0;
        }
        p->prot_state = UP_PACKET_IDLE;
    }
    else
    {
        WD_ERR("read response failed!!!\n");
    }

    return ret;
}

int readCRC(unsigned int addr, int len)
{
	UPGRADE_PARAM *this = &upgrade_param;
    uint8 buf[500] = {0xAA, 0xA6, 0x08, 0x00};
    int cmd_len = 4+4+4+2;

    buf[4] = addr & 0xff;
    buf[5] = (addr>>8) & 0xff;
    buf[6] = (addr>>16) & 0xff;
    buf[7] = (addr>>24) & 0xff;

    buf[8] = len & 0xff;
    buf[9] = (len>>8) & 0xff;
    buf[10] = (len>>16) & 0xff;
    buf[11] = (len>>24) & 0xff;

    buf[13] = 0x55;
    buf[12] = Check_BCC(buf, cmd_len);

    boot_write_usb(buf, 250);

    UP_PROT_PACKET *p = &(upgrade_param.prot_packet_usb);
    int ret = -1;
    uint8 buf_read[500] = {0};

    this->crc_value_dev = 0;

    int read_len = 0;
    read_len = boot_read_usb(buf_read, 64);
    if(0 < read_len)
    {
        D_DBG("read %d byte.\n", read_len);

        p->prot_state = UP_PACKET_IDLE;
        if((0 == parseProtocal(buf_read, read_len))\
            &&(UP_PACKET_RECV_SUCCESS == p->prot_state))
        {
            this->crc_value_dev = (p->prot_data[0]) | ((p->prot_data[1])<<8);
            ret = 0;
        }
        p->prot_state = UP_PACKET_IDLE;
    }
    else
    {
        WD_ERR("read response failed!!!\n");
    }

    return ret;
}

int downloadCRCValue(unsigned int len, unsigned short crc, unsigned int addr)
{
	UPGRADE_PARAM *this = &upgrade_param;

    uint8 buf[500] = {0xAA, 0xD9, 0x0A, 0x00};
    int cmd_len = 4+4+2+4+2;



    buf[4] = len & 0xff;
    buf[5] = (len>>8) & 0xff;
    buf[6] = (len>>16) & 0xff;
    buf[7] = (len>>24) & 0xff;

    buf[8] = crc & 0xff;
    buf[9] = (crc>>8) & 0xff;

    buf[10] = addr & 0xff;
    buf[11] = (addr>>8) & 0xff;
    buf[12] = (addr>>16) & 0xff;
    buf[13] = (addr>>24) & 0xff;

    buf[15] = 0x55;
    buf[14] = Check_BCC(buf, cmd_len);

    boot_write_usb(buf, 250);

    UP_PROT_PACKET *p = &(upgrade_param.prot_packet_usb);
    int ret = -1;
    uint8 buf_read[500] = {0};

    this->crc_value_dev = 0;

    int read_len = 0;
    read_len = boot_read_usb(buf_read, 64);
    if(0 < read_len)
    {
        D_DBG("read %d byte.\n", read_len);

        p->prot_state = UP_PACKET_IDLE;
        if((0 == parseProtocal(buf_read, read_len))\
            &&(UP_PACKET_RECV_SUCCESS == p->prot_state))
        {
            if((1 == p->prot_data_cnt)&&(0 == p->prot_data[0]))
                ret = 0;
        }
        p->prot_state = UP_PACKET_IDLE;
    }
    else
    {
        WD_ERR("read response failed!!!\n");
    }

    return ret;
}

int checkCRC(void)
{
    return 0;
}

int securityCode(void)
{
    uint8 buf[500] = {0xAA, 0xCC, 0x00, 0x00, 0x00, 0x55};
    int cmd_len = 4+2;

    buf[4] = Check_BCC(buf, cmd_len);

    boot_write_usb(buf, cmd_len);

    UP_PROT_PACKET *p = &(upgrade_param.prot_packet_usb);
    int ret = -1;
    uint8 buf_read[500] = {0};
    int read_len = 0;
    read_len = boot_read_usb(buf_read, 64);
    if(0 < read_len)
    {
        //D_DBG("read %d byte.\n", read_len);
        p->prot_state = UP_PACKET_IDLE;
        if((0 == parseProtocal(buf_read, read_len))\
            &&(UP_PACKET_RECV_SUCCESS == p->prot_state))
        {
            //memcpy(this->dev_sn, p->prot_data, p->prot_data_cnt);
            if((1 == p->prot_data_cnt)&&(0 == p->prot_data[0]))
                ret = 0;
        }
        p->prot_state = UP_PACKET_IDLE;
    }
    else
    {
        WD_ERR("read response failed!!!\n");
    }

    return ret;
}

int runAPP(void)
{
    uint8 buf[500] = {0xAA, 0xE3, 0x00, 0x00, 0x00, 0x55};
    int cmd_len = 4+2;

    buf[4] = Check_BCC(buf, cmd_len);
    DBG("===============>runAPP enter \n");
    DBG("runAPP buf[4] = 0x%02x \n", buf[4]);
    usleep(10000);
    app_boot_write_usb(buf, cmd_len);

    UP_PROT_PACKET *p = &(upgrade_param.prot_packet_usb);
    int ret = -1;
    uint8 buf_read[500] = {0};
    int read_len = 0;
    read_len = boot_read_usb(buf_read, 64);
    if(0 < read_len)
    {
        //D_DBG("read %d byte.\n", read_len);
        p->prot_state = UP_PACKET_IDLE;
        if((0 == parseProtocal(buf_read, read_len))\
            &&(UP_PACKET_RECV_SUCCESS == p->prot_state))
        {
            //memcpy(this->dev_sn, p->prot_data, p->prot_data_cnt);
            if((1 == p->prot_data_cnt)&&(0 == p->prot_data[0]))
                ret = 0;
        }
        p->prot_state = UP_PACKET_IDLE;
    }
    else
    {
        WD_ERR("read response failed!!!\n");
    }
    DBG("<===============>runAPP exit \n");

    return ret;
}

int selfTest(void)
{

    return 0;
}

#if 0
int read_fw_upgrade_flag(void)
{
	FILE *file;
	int file_size = 0;
	int read_size = 0;
	int upgrade_flag = 0;
	char str[256] = {0};
	int ret = -1;

	file = fopen(FW_UPGRADE_FLAG_FILE, "r");
	if(NULL == file)
	{
		D_DBG("%s open failed!\n", FW_UPGRADE_FLAG_FILE);
		return -1;
	}

	file_size = get_file_size(FW_UPGRADE_FLAG_FILE);
	if((0 == file_size) || (256 < file_size))//此处最大文件大小待确认
	{
		WD_ERR("%s file_size = %d, error!\n", FW_UPGRADE_FLAG_FILE, file_size);
		fclose(file);
		return -1;
	}

	read_size = fread(str, 1, file_size, file);
	D_DBG("read_size = %d\n", read_size);
	if(file_size != read_size)
	{
		WD_ERR("file_size = %d, read_size = %d, read file failed!\n", file_size, read_size);
		fclose(file);
		return -1;
	}
	fclose(file);//释放资源, add by hcq, 20231030

	sscanf(str, "%d", &upgrade_flag);
	WD_DBG("upgrade_flag = %d\n", upgrade_flag);

	if(0 >= upgrade_flag)
	{
		ret = -1;
		goto end;
	}

	ret = 0;

end:
	return ret;
}

int change_fw_upgrade_flag(void)
{
	FILE *file;
	static uint8 upgrade_times = 0;
	int file_size = 0;
	int read_size = 0;
	int write_size = 0;
	int upgrade_flag = 0;
	char str[256] = {0};
	int ret = -1;

	if(0 < upgrade_times)
	{
		WD_DBG("upgrade_flag has been changed.\n");
		ret = 0;
		goto end;
	}

	file = fopen(FW_UPGRADE_FLAG_FILE, "r");
	if(NULL == file)
	{
		D_DBG("%s open failed!\n", FW_UPGRADE_FLAG_FILE);
		return -1;
	}

	file_size = get_file_size(FW_UPGRADE_FLAG_FILE);
	if((0 == file_size) || (256 < file_size))//此处最大文件大小待确认
	{
		WD_ERR("%s file_size = %d, error!\n", FW_UPGRADE_FLAG_FILE, file_size);
		fclose(file);
		return -1;
	}

	read_size = fread(str, 1, file_size, file);
	D_DBG("read_size = %d\n", read_size);
	if(file_size != read_size)
	{
		WD_ERR("file_size = %d, read_size = %d, read file failed!\n", file_size, read_size);
		fclose(file);
		return -1;
	}
	fclose(file);//释放资源, add by hcq, 20231030

	sscanf(str, "%d", &upgrade_flag);
	WD_DBG("upgrade_flag = %d\n", upgrade_flag);

	if(0 >= upgrade_flag)
	{
		ret = -1;
		goto end;
	}

	memset(str, 0x00, 256);
	upgrade_flag--;
	snprintf(str, 256, "%d", upgrade_flag);
	WD_DBG("upgrade_flag = %d\n", upgrade_flag);
	file = fopen(FW_UPGRADE_FLAG_FILE, "w");
	if(NULL == file)
	{
		WD_ERR("%s open failed!\n", FW_UPGRADE_FLAG_FILE);
		ret = -1;
		goto end;
	}
	write_size = fwrite(str, 1, strlen(str), file);
	if(strlen(str) != write_size)
	{
		WD_ERR("%s open failed!\n", FW_UPGRADE_FLAG_FILE);
		ret = -1;
		fclose(file);
		goto end;
	}

	upgrade_times++;
	ret = 0;
	fclose(file);
end:
	return ret;
}
#endif

int read_fw_version(void)
{
	FILE *file;
	int file_size = 0;
	int read_size = 0;
	int fw_version = 0;
	char firmware_name[256] = {0};

	if(0 != read_fw_upgrade_flag())
	{
		D_DBG("read_fw_upgrade_flag: FAIL!\n");
		return -1;
	}

	file = fopen(FW_VERSION_FILE, "r");
	if(NULL == file)
	{
		D_DBG("%s open failed!\n", FW_VERSION_FILE);
		return -1;
	}

	file_size = get_file_size(FW_VERSION_FILE);
	if((0 == file_size) || (256 < file_size))//此处最大文件大小待确认
	{
		WD_ERR("%s file_size = %d, error!\n", FW_VERSION_FILE, file_size);
		fclose(file);
		return -1;
	}

	read_size = fread(firmware_name, 1, file_size, file);
	D_DBG("read_size = %d\n", read_size);
	if(file_size != read_size)
	{
		WD_ERR("file_size = %d, read_size = %d, read file failed!\n", file_size, read_size);
		fclose(file);
		return -1;
	}

	firmware_name[read_size-1] = 0;

	snprintf(new_firmware_name, 512, "%s%s.bin", CONF_FILE_PATH, firmware_name);
	WD_DBG("new_firmware_name = %s\n", new_firmware_name);

	sscanf(firmware_name, "ACM32FP_V%d", &fw_version);
	WD_DBG("fw_version = %d\n", fw_version);

	snprintf(new_firmware_version, 256, "acm32_btl_ofilm_pc_%06d", fw_version);
	WD_DBG("new_firmware_version = %s\n", new_firmware_version);

	new_firmware_version_num = fw_version;
	WD_DBG("new_firmware_version_num = %d\n", new_firmware_version_num);
	fclose(file);//释放资源, add by hcq, 20231030

	return 0;
}

char *upgrade_new_firmware_version(void)
{
	return new_firmware_version;
}

char *upgrade_new_firmware_name(void)
{
	return new_firmware_name;
}

uint32 upgrade_new_firmware_version_num(void)
{
	return new_firmware_version_num;
}

int upgrade_and_run(void)
{
	//打开并读取文件
	UPGRADE_PARAM *this = &upgrade_param;
	FILE *file;
	int file_size = 0;
	int read_size = 0;
	int ret = -1;
    D_DBG("===================>enter \n");
    if(0 > boot_open_dev())
    {
        WD_DBG("open_dev failed!!!\n");
        return -1;
    }


    file = fopen(UPGRADE_FILE, "rb");
	if(NULL == file)
	{
		WD_ERR("%s open failed!\n", UPGRADE_FILE);
		boot_close_dev();

        D_DBG("<===================exit \n");
		return -2;//文件未打开则直接取消升级，modified by hcq, 20230425
	}

	file_size = get_file_size(UPGRADE_FILE);
	if((0 == file_size) || (2*1024*1024 < file_size))//此处最大文件大小待确认
	{
		WD_ERR("%s file_size = %d, error!\n", UPGRADE_FILE, file_size);
		boot_close_dev();
		fclose(file);//释放资源，by hcq, 20231030

        D_DBG("<===================exit \n");
		return -1;
	}
	D_DBG("file_size = %d\n", file_size);

	uint8 *file_data = (uint8 *)calloc(1, file_size);

	read_size = fread(file_data, 1, file_size, file);
	D_DBG("read_size = %d\n", read_size);
	if(file_size != read_size)
	{
		WD_ERR("file_size = %d, read_size = %d, read file failed!\n", file_size, read_size);
		goto upgrade_and_run_end;
	}

	set_upgrade_state(1);

    char *data = (char *)file_data;
    int addr = 0;
    int size = file_size;
    this->crc_value_file = CRC16_X25(data, size);
    this->crc_value_dev = 0;
    D_DBG("size = %d", size);
    D_DBG("crc_value = 0x%04x", this->crc_value_file);

    if(0 > eraseEFlash())
    {
        WD_ERR("eraseEFlash failed!!!\n");
        goto upgrade_and_run_end;
    }

    int count = size/DOWNLOAD_DATA_LEN_MAX;
    for(int i = 0; i < count; i++)
    {
        if(0 != downloadCodeToEFlash(addr, data+addr, DOWNLOAD_DATA_LEN_MAX))
        {
            WD_ERR("downloadCodeToEFlash: failed!!!\n");
            goto upgrade_and_run_end;
        }
        addr += DOWNLOAD_DATA_LEN_MAX;
    }

    if((0 < size%DOWNLOAD_DATA_LEN_MAX)
        && (0 != downloadCodeToEFlash(addr, data+addr, size%DOWNLOAD_DATA_LEN_MAX)))
    {
        WD_ERR("downloadCodeToEFlash: failed!!!\n");
        goto upgrade_and_run_end;
    }

    if(0 != readCRC(0x00000000, size))
    {
        WD_ERR("readCRC: failed!!!\n");
        goto upgrade_and_run_end;
    }

    if(this->crc_value_dev != this->crc_value_file)
    {
        WD_ERR("check CRC: error!!!\n");
        goto upgrade_and_run_end;
    }

    if(0 != downloadCRCValue(size, this->crc_value_file, 0x00))
    {
        WD_ERR("downloadCRC: failed!!!\n");
        goto upgrade_and_run_end;
    }

    if(0 > securityCode())
    {
        WD_ERR("securityCode failed!!!\n");
        goto upgrade_and_run_end;
    }

	ret = 0;
    WD_LOG("downloadCodeToEFlash: success.\n");
    if(0 == runAPP())
    {
    	WD_LOG("runAPP: success.\n");
    }
#if 0
    char system_cmd[200] = "rm ";
    //strncat(system_cmd, UPGRADE_FILE, sizeof(UPGRADE_FILE));
    strncat(system_cmd, UPGRADE_FILE, 100);
    D_DBG("%s\n", system_cmd);
    system(system_cmd);

    char rm_oms_conf_cmd[200] = "rm ";
    strncat(rm_oms_conf_cmd, FW_VERSION_FILE, 100);
    D_DBG("%s\n", rm_oms_conf_cmd);
    system(rm_oms_conf_cmd);
#else
	change_fw_upgrade_flag();
#endif
	set_upgrade_state(0);
upgrade_and_run_end:
    D_DBG("upgrade_and_run end.\n");
    free(file_data);
    fclose(file);
    boot_close_dev();
    D_DBG("<===================exit \n");

    return ret;
}

int readSN(void)
{
	UPGRADE_PARAM *this = &upgrade_param;

    uint8 buf[500] = {0xAA, 0xA0, 0x00, 0x00, 0x00, 0x55};
    int cmd_len = 4+2;

    buf[4] = Check_BCC(buf, cmd_len);

    //boot_write_usb(buf, cmd_len);
    boot_write_usb(buf, 250);

    UP_PROT_PACKET *p = &(upgrade_param.prot_packet_usb);
    int ret = -1;
    memset(this->dev_sn, 0x00, 64);
    uint8 buf_read[500] = {0};
    int read_len = 0;
    read_len = boot_read_usb(buf_read, 64);
    if(0 < read_len)
    {
        D_DBG("read %d byte.\n", read_len);
        p->prot_state = UP_PACKET_IDLE;
        if((0 == parseProtocal(buf_read, read_len))\
            &&(UP_PACKET_RECV_SUCCESS == p->prot_state))
        {
            memcpy(this->dev_sn, p->prot_data, p->prot_data_cnt);
            ret = 0;
        }
        p->prot_state = UP_PACKET_IDLE;
    }
    else
    {
        WD_ERR("read response failed!!!\n");
    }

    return ret;
}

int parseProtocal(unsigned char *data, int len)
{
	UPGRADE_PARAM *this = &upgrade_param;

    uint8 getchar = 0;
    UP_PROT_PACKET *p = &(upgrade_param.prot_packet_usb);
    int32 ret = -1;
    //D_DBG("received data len = %d:\n", len);

#if 0
    for(int i = 0; i < len; i++)
    {
        DBG("0x%02x ", data[i]);
    }
    DBG("\n");
#endif

/*对USB的命令数据进行处理*/
    for(int i = 0; i < len; i++)
    {
        getchar = data[i];

        switch (p->prot_state)
        {
            case UP_PACKET_IDLE:
                if (getchar == 0xAA)
                {
                    p->prot_state = UP_PACKET_TYPE;
                    p->prot_head = getchar;
                    this->usb_recv_cnt = 0;
                    this->usb_recv_data[(this->usb_recv_cnt)++]=getchar;
                }
                break;
            case UP_PACKET_TYPE:
                p->prot_type = getchar;
                p->prot_state = UP_PACKET_SIZE1;
                this->usb_recv_data[(this->usb_recv_cnt)++]=getchar;
                break;
            case UP_PACKET_SIZE1:
                p->prot_size  = 0;
                p->prot_size |= getchar;
                p->prot_state = UP_PACKET_SIZE2;
                this->usb_recv_data[(this->usb_recv_cnt)++]=getchar;
                break;
            case UP_PACKET_SIZE2:	//包长度 = 数据内容长度 + 校验位长度
                p->prot_size |= (getchar<<8);
                //D_DBG("packet size = %d\n", p->prot_size);
                p->prot_data_cnt = 0;
                if (p->prot_size > 0)				//有数据
                {
                    p->prot_state = UP_PACKET_DATA;
                }
                else if (p->prot_size == 0)	//无数据，直接到校验位
                {
                    p->prot_state = UP_PACKET_BCC;
                }
                else
                {
                    p->prot_state = UP_PACKET_IDLE;
                }

                this->usb_recv_data[(this->usb_recv_cnt)++] = getchar;
                break;
            case UP_PACKET_DATA:
                p->prot_data[p->prot_data_cnt] = getchar;
                p->prot_data_cnt++;

                if(p->prot_size <= p->prot_data_cnt)
                {
                    p->prot_state = UP_PACKET_BCC;
                }

                this->usb_recv_data[(this->usb_recv_cnt)++]=getchar;
                break;
            case UP_PACKET_BCC:
                p->prot_bcc  = getchar;
                p->prot_state = UP_PACKET_END;

                this->usb_recv_data[(this->usb_recv_cnt)++]=getchar;
                break;
            case UP_PACKET_END:
                p->prot_end = getchar;
                this->usb_recv_data[(this->usb_recv_cnt)++] = getchar;
                //D_DBG("bcc = %d\n", this->Check_BCC(usb_recv_data, usb_recv_cnt));

                if((0x55 == p->prot_end)&&(0 == Check_BCC(this->usb_recv_data, this->usb_recv_cnt)))
                {
                    p->prot_respond = 0;
                    p->prot_state = UP_PACKET_RECV_SUCCESS;
                    //D_DBG("Recv %d bytes data from device.\n", usb_recv_cnt);
                    this->usb_recv_cnt=0;
                    ret = 0;
                    return ret;
                }
                else
                {
                    WD_ERR("Recv data from device error!!!\n");
                    p->prot_state = UP_PACKET_ERROR;
                }
                break;
            default:
                break;
        }
    }

    return ret;
}
#if 0
int32 rm_firmware_file(void)
{
    char system_cmd[200] = "rm ";
    //strncat(system_cmd, UPGRADE_FILE, sizeof(UPGRADE_FILE));
    strncat(system_cmd, UPGRADE_FILE, 100);
    D_DBG("%s\n", system_cmd);
    system(system_cmd);

    char rm_oms_conf_cmd[200] = "rm ";
    strncat(rm_oms_conf_cmd, FW_VERSION_FILE, 100);
    D_DBG("%s\n", rm_oms_conf_cmd);
    system(rm_oms_conf_cmd);

	return 0;
}
#endif
int32 set_upgrade_state(uint8 state)
{
	WD_LOG("state %d\n", state);
	UPGRADE_PARAM *this = &upgrade_param;
	this->upgrade_state = state;
	return 0;
}

uint8 get_upgrade_state(void)
{
	UPGRADE_PARAM *this = &upgrade_param;
	return this->upgrade_state;
}


int32 upgrade_module_init(void)
{
	UPGRADE_PARAM *this = &upgrade_param;
    this->usb_handle = NULL;

    this->udev.vid = BOOT_USB_VID;
    this->udev.pid = BOOT_USB_PID;
    this->usb_recv_cnt = 0;
	this->upgrade_state = 0;
    //this->udev_desc.bDeviceClass = LIBUSB_CLASS_HID;
    //this->udev_desc.bDeviceSubClass = LIBUSB_CLASS_HID;
    //this->udev_desc.
    //this->udev_desc
#if 0
    ret = get_device_endpoint(&udev_desc, &udev);
    if(0 > ret)
    {
        WD_ERR("get_device_endpoint failed.\n");
    }
#endif

	return DRV_OK;
}


